/*
 * server_session.cpp
 *
 *  Created on: Aug 1, 2013
 *      Author: killerg
 */

#include "logon_deps.h"
#include "server_session.h"
#include "server_mgr.h"
#include "logon.h"
#include "logon_cfg.h"

#include "share/net_s.h"
#include "share/msg.h"
#include "share/cl_msg.pb.h"
#include "share/sl_msg.pb.h"
#include "share/patterns.h"
#include "share/util.h"

bool server_session_t::send_msg(sl::LMsg* &msg) {
    return g_logon.svrsess_mgr->send_msg(this, msg);
}


void server_session_t::on_connect() {

}

void server_session_t::on_disconnect() {
    if (!g_logon.svrmgr->is_valid_serverid(serverid))
        return;

    server_info_t &info = g_logon.svrmgr->info[serverid];

    info.status = co::ESS_Down;
    info.sess = NULL;

    UTIL_LOG(T, "server disconnected");
}

void handle_default(server_session_t* sess, sl::SMsg* msg) {
}

void handle_slogon(server_session_t* sess, sl::SMsg* msg) {
    auto slogon = msg->logon();

    int32_t serverid = slogon.serverid();

    bool ok = true;
    if (!g_logon.svrmgr->is_valid_serverid(serverid)) {
        ok = false;
    	sess->_trans->disconnect();
    	return;
    } else if (!g_logon.svrmgr->info[serverid].sess) {
        g_logon.svrmgr->info[serverid].ip = slogon.ip();
        g_logon.svrmgr->info[serverid].port = slogon.port();
        g_logon.svrmgr->info[serverid].sess = sess;
        g_logon.svrmgr->info[serverid].name = slogon.name();
        if (serverid > g_logon.svrmgr->maxid)
        	g_logon.svrmgr->maxid = serverid;
    } else {
    	sess->_trans->disconnect();
    	return;
    }

    sess->serverid = serverid;

    CREATE_SL_LMSG(LLogon, logon);
    logon->set_ok(ok);
    sess->send_msg(___msg);
    UTIL_LOG(T, "server logon");
}

void handle_sstatus(server_session_t* sess, sl::SMsg* msg) {
    auto status = msg->status();

    if (!g_logon.svrmgr->is_valid_serverid(sess->serverid))
        return;

    server_info_t &info = g_logon.svrmgr->info[sess->serverid];

    info.status = status.status();
    info.new_server = status.new_server();

    //UTIL_LOG(T, "server status");
}

void handle_splayerlogon(server_session_t* sess, sl::SMsg* msg) {
    g_logon.svrmgr->info;
//    UTIL_LOG(T, "player has logon server");
}

void handle_splayerwilllogon(server_session_t* sess, sl::SMsg* msg) {
    auto &playerwilllogon = msg->playerwilllogon();

    client_session_t* clisess = g_logon.clisess_mgr->base::connmgr.map_id.get(playerwilllogon.sessid());
    if (NULL == clisess)
        return;

    int64_t playerid = clisess->playerid + int64_t(sess->serverid) * co::MaxAccountNum;
    server_info_t &info = g_logon.svrmgr->info[sess->serverid];
    std::string ip;
    int32_t port = -1;
    int32_t key = -1;
    cl::ELSelectErr error;

    if (info.status == co::ESS_Running && info.sess) {
        error = cl::ELSE_Ok;
        ip = info.ip;
        port = info.port;
        key = clisess->key;
    } else {
    	if (info.status == co::ESS_Busy) {
    	    error = cl::ELSE_ServerBusy;
    	} else {
    	    error = cl::ELSE_ServerOffline;
    	}
    }

    CREATE_CL_LMSG(LSelect, select);
    select->set_key(key);
    select->set_ip(ip);
    select->set_port(port);
    select->set_playerid(playerid);
    select->set_error(error);
    clisess->send_msg(___msg);

    clisess->stage = ELSelected;
}

void handle_splayerlogout(server_session_t* sess, sl::SMsg* msg) {
    UTIL_LOG(T, "player has logout server");
}

bool serversess_mgr_t::init() {

    bool ok = base::init(
            g_cfg->ListenServerIp.c_str(),
            g_cfg->ListenServerPort,
            300,
            10000,
            10.0f,
            0xffffffff,
            false
            );
    if (!ok) {
        UTIL_LOG(E, "serversess_mgr_t::init init err %s:%d",
                g_cfg->ListenServerIp.c_str(),
                g_cfg->ListenServerPort);

        return false;
    }

    UTIL_LOG(I, "listening for server at %s:%d",
            g_cfg->ListenServerIp.c_str(),
            g_cfg->ListenServerPort);

    ok = ok && base::reg(sl::ID_SLogon, handle_slogon);
    ok = ok && base::reg(sl::ID_SStatus, handle_sstatus);
    ok = ok && base::reg(sl::ID_SPlayerWillLogon, handle_splayerwilllogon);
    ok = ok && base::reg(sl::ID_SPlayerLogon, handle_splayerlogon);
    ok = ok && base::reg(sl::ID_SPlayerLogout, handle_splayerlogout);

    return ok;
}
